/***********************************************************************
	filename: 	DaterSystem.cpp
	created:	16/04/2012
	author:		4Ys

	purpose:	Implementation of main system object
*************************************************************************/

#include "DaterSystem.h"
#include "DaterEventFacotryManager.h"
#include "DaterEventManager.h"
#include "DaterUserManager.h"
#include "DaterTplEventFactory.h"
#include "DaterNormalEvent.h"
#include "DaterMessageQueue.h"
#include "DaterClientSocket.h"
#include "DaterGroupManager.h"

namespace Dater
{
	//----------------------------------------------------------------------------//
	template<> System* Singleton<System>::ms_Singleton	= 0;

	//----------------------------------------------------------------------------//
	System& System::create()
	{
		return *new System();
	}

	//----------------------------------------------------------------------------//
	void System::destroy()
	{
		delete System::getSingletonPtr();
	}

	//----------------------------------------------------------------------------//
	System&	System::getSingleton(void)
	{
		return Singleton<System>::getSingleton();
	}

	//----------------------------------------------------------------------------//
	System*	System::getSingletonPtr(void)
	{
		return Singleton<System>::getSingletonPtr();
	}

	//----------------------------------------------------------------------------//
	System::System()
	{
		_calendarData = new CalendarData();

		_dateRegex = "^(?:(?!0000)[0-9]{4}([-/.]?)(?:(?:0?[1-9]|1[0-2])\\1(?:0?[1-9]|1[0-9]|2[0-8])|(?:0?[13-9]|1[0-2])\\1(?:29|30)|(?:0?[13578]|1[02])\\1(?:31))|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)([-/.]?)0?2\\2(?:29))$";

		_timeRegex = "^([0-9]|1[0-9]|2[0-3]):([0-9]|[0-5][0-9])$";

		// create the core system singleton objects
		createSingletons();

		// add the window factories for the core window types
		addStandardEventFactories();
	}

	//----------------------------------------------------------------------------//
	System::~System(void)
	{
		// destroy windows so it's safe to destroy factories
		EventManager::getSingleton().destroyAllEvents();

		// remove factories so it's safe to unload GUI modules
		EventFactoryManager::getSingleton().removeAllFactories();

		UserManager::getSingleton().removeAllUsers();

		// cleanup singletons
		destroySingletons();

		delete _calendarData;
	}

	//----------------------------------------------------------------------------//
	void System::addStandardEventFactories()
	{
		// Add factories for types all base elements
		EventFactoryManager::addFactory< TplEventFactory<NormalEvent> >();
		EventFactoryManager::addFactory< TplEventFactory<GroupEvent> >();
	}

	//----------------------------------------------------------------------------//
	void System::createSingletons()
	{
		// cause creation of other singleton objects
		new EventFactoryManager();
		new EventManager();
		new UserManager();
		new RecvMessageQueue();
		new SendMessageQueue();
		new GroupManager();
	}

	//----------------------------------------------------------------------------//
	void System::destroySingletons()
	{
		delete  EventManager::getSingletonPtr();
		delete  EventFactoryManager::getSingletonPtr();
		delete  UserManager::getSingletonPtr();
		delete	RecvMessageQueue::getSingletonPtr();
		delete	SendMessageQueue::getSingletonPtr();
		delete	GroupManager::getSingletonPtr();
	}

	//----------------------------------------------------------------------------//

	CalendarData* System::getCalendarData() const
	{
		return _calendarData;
	}

	unsigned int __stdcall System::netThreadFunction(void* args)
	{
		((ClientSocket*)args)->startListen();

		return 0;
	}

	void System::startSocketListenThread(Dater::ClientSocket* clientSocket)
	{
		_netThread = (HANDLE)_beginthreadex(NULL, 0, netThreadFunction, clientSocket, 0, &_threadAddr);
	}
}